package demo.netflix.hystrix.command;

import java.util.Random;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.netflix.hystrix.HystrixCommand;
import com.netflix.hystrix.HystrixCommandGroupKey;
import com.netflix.hystrix.HystrixCommandKey;
import com.netflix.hystrix.HystrixCommandProperties;
import com.netflix.hystrix.HystrixThreadPoolKey;
import com.netflix.hystrix.HystrixThreadPoolProperties;

import demo.java.lang.ThreadDemo;

public class HystrixCommandDemo extends HystrixCommand<String> {

    private static Logger logger = LoggerFactory.getLogger(HystrixCommandDemo.class);

    private final String name;

    static Random random = new Random();

    public HystrixCommandDemo(String name) {
        super(HystrixCommand.Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("CommandGroup1"))
                // CommandKey：依赖名称，依赖隔离的根本就是对相同CommandKey的依赖做隔离
                .andCommandKey(HystrixCommandKey.Factory.asKey("CommandKey1"))
                // 配置线程池隔离
                .andThreadPoolKey(HystrixThreadPoolKey.Factory.asKey("ThreadPool1"))
                // Command 配置
                .andCommandPropertiesDefaults(HystrixCommandProperties.Setter()
                        // 设置隔离方式为线程隔离（默认也是采用线程隔离）
                        .withExecutionIsolationStrategy(HystrixCommandProperties.ExecutionIsolationStrategy.THREAD)
                        // 是否启用超时配置。默认true
                        .withExecutionTimeoutEnabled(true)
                        // 配置超时时间
                        .withExecutionTimeoutInMilliseconds(10_000)
                        // 当执行线程执行超时时，是否进行中断处理，默认为true
                        .withExecutionIsolationThreadInterruptOnTimeout(true))
                // 线程池配置
                .andThreadPoolPropertiesDefaults(HystrixThreadPoolProperties.Setter()
                        // 线程池大小，默认值10个。
                        .withCoreSize(2)
                        // 最大队列长度，默认-1。如果设置为-1，使用的是SynchronousQueue，否则正数将会使用LinkedBlockingQueue
                        .withMaxQueueSize(0)));
        logger.info("调用构造方法with {}", name);
        this.name = name;
    }

    @Override
    protected String run() {
        logger.info("任务：{} 开始执行 ", name);
        if (name.endsWith("Han")) {
            throw new RuntimeException("this command always fails");
        }
        /*
         * 网络调用 或者其他一些业务逻辑，可能会超时或者抛异常
         */
        ThreadDemo.safeSleep(random.nextInt(9_000));
        return "Hello " + name + "!";
    }

    @Override
    protected String getFallback() {
        logger.warn("getFallback {}", name);
        return "getFallback " + name + "!";
    }
}